import { ETaskState } from "GameLoop/DecisionMaking/TaskDeclare/type";
import { InnerMineEntity, MinerialEntity } from "GameLoop/WorldState/EntityManager/Entitys";
import { WorldState } from "GameLoop/WorldState/worldstate";
import { structurePriority } from "utils/constants/priorityconstant";
import { BodyEfficiency } from "utils/creep/bodyEfficiency";
import { PositionHelper } from "utils/position/PositionHelper";


export class CreepTaskChecker
{
    public static notify:Notify

   
    public static check(room:Room,task:ITaskDeclare["creep"])
    {
        switch(task.data.type)
        {
            case "build":
                return this.checkBuild(room,task as any);
            case "helpBuild":
                return this.checkHelpBuild(room,task as any);
            case "harvest":
                return this.checkHarvest(room,task as any);
            case "harvestM":
                return this.checkHarvestMinerial(room,task as any);
            case "depo":
                return this.checkHarvestDepo(room,task as any);
            case "repair":
                return this.checkRepair(room,task as any);
            case "upgrade":
                return this.checkUpgrade(room,task as any);
            case "fill":
                return this.checkFill(room,task as any);
            case "scout":
                return this.checkScout(room,task as any);
            case "claim":
                return this.checkClaim(room,task as any);
            case "transport":
                return this.checkTransport(room,task as any);
            case "transportAccurate":
                return this.checkTransportAccurate(room,task as any);
        }
    }
    
    private static checkHarvest(room:Room,task:ITask<ICreepTaskData<"harvest">,"creep">):ETaskState
    {
         
       
        const bindMine = room.getEntityByID<InnerMineEntity>(task.data.arg.entityId);
        if(!bindMine)
        {
            return ETaskState.Complete
        }
        const memorysites = bindMine.getNodeMemory().sites;
        if(memorysites)
        {
            for(let i =0;i<memorysites.length;)
            {
                const site = Game.getObjectById(memorysites[i]);
                if(!site)
                {
                    memorysites.splice(i,1);
                }
                else
                {
                    i++;
                }
            }
        } 

        if(room.getType() ==1&&  room.canExecute(100))
        {
            // 房间类型为1是不可能出现source找不到的情况的
            const soutce = bindMine.getSource();
            if(!soutce)
            {
                Memory.Debug[`${room.name}类型错误`]='找不到source'
            }
            else 
            {
                if(soutce.effects && soutce.effects.find(e=>e.effect == PWR_REGEN_SOURCE))
                {
                    task.data.bodyconfig=[
                        {
                            Role:'mine',
                            body:[[WORK,20],[CARRY,4],[MOVE,10]],
                            isAdapt:true,
                        }
                    ]
                }
                else 
                {
                    task.data.bodyconfig=undefined
                }
            }
            
        }
        if(memorysites?.length==0)
        {
           delete bindMine.getNodeMemory().sites
        }
        const repobjects = bindMine.getNodeMemory().repairObjects;
        if(repobjects)
        {
            for(let i =0;i<repobjects.length;)
            {
                const obj = Game.getObjectById(repobjects[i]);
                if(!obj || obj.hits>=obj.hitsMax)
                {
                    repobjects.splice(i,1);
                }
                else
                {
                    i++;
                }
            }
        }
       
        if(repobjects?.length==0)
        {
           delete bindMine.getNodeMemory().repairObjects
        }
        const creeps =  task.data.creeps.map(e=>Game.creeps[e]);
        if(room.canExecute(3031))
        {
            const index = task.data.required.findIndex(e=>e[0][0]=="porter_w");
            if(index!=-1)
            {
                task.data.required[index][1]=1;
            }
        }
        if(room.canExecute(51))
        {
            bindMine.updateMemory();
          
            if(  bindMine.Link)
            {
                task.data.required.forEach(e=>
                {
                    if( _.intersection(e[0],["porter","porter_w"]).length)
                    {
                        e[1]=0;
                    }
                })
            }
            else 
            {
                const container = bindMine.getContainer();
     
                if( 
                    ( creeps.some(e=>e.ActiveRole() == "mine") 
                    && !memorysites?.length)
                     )

                {
                    if((
                        (container && container.store.getUsedCapacity()>1500) 
                            ||bindMine.getPickUpItem(RESOURCE_ENERGY,100).length>0
                        ))
                        {
                            task.data.required.forEach(e=>
                                {
                                    if(e[0].includes("porter"))
                                    {
                                        if(e[1]<(e[2]))
                                        {
                                            e[1]++;
                                        }
                                    }
                                    else 
                                    {
                                        e[1]=e[2]!
                                    }
                                    
                                })
                        }
                        else if((
                            (container && container.store.getUsedCapacity()<100) 
                                
                            ))
                            {
                                task.data.required.forEach(e=>
                                    {
                                        if(e[0].includes("porter"))
                                        {
                                            if(e[1]>1)
                                            {
                                                e[1]--;
                                            }
                                        }
                                        else 
                                        {
                                            e[1]=e[2]
                                        }
                                        
                                    })
                            }
                }
                else 
                {
                    
                    if((
                        (container && container.store.getUsedCapacity()==0) 
                             && bindMine.getPickUpItem(RESOURCE_ENERGY,100).length==0
                        ))
                    {
                        // 没有mine 有site 容器无能量 。没有可拾取的能量
                            task.data.required.forEach(e=>
                            {
                                if(e[0].includes("porter"))
                                {
                                    e[1]=0;
                                }
                                else  if(e[0].includes("porter_w"))
                                {
                                    e[1]=0;
                                }
                            });
                            
                            const freecreeps = creeps.filter(e=>e.ActiveRole() == "porter"||e.ActiveRole() == "porter_w");
                            room.freeTaskCreeps<ITaskDeclare["creep"]>(task ,freecreeps);
                    }
                    else 
                    {
                        task.data.required.forEach(e=>
                            {
                                if(e[0].includes("porter"))
                                {
                                    e[1]=1;
                                }
                                else  if(e[0].includes("porter_w"))
                                {
                                    e[1]=0;
                                }
                            })
                    }
                }
            }
        }
        
        return ETaskState.Running
    }
    private static checkHarvestMinerial(room:Room,task:ITask<ICreepTaskData<"harvestM">>):ETaskState
    {
       
        const bindMine = room.getEntityByID<MinerialEntity>(task.data.arg.entityId);
        if(!bindMine)
        {
            
            return ETaskState.Complete
        }
        const minerial = bindMine.getMinerial();
        
        if(minerial && minerial.mineralAmount==0)
        {
            return ETaskState.Complete
        }
        if(task.data.creeps.length>1)
        {
            task.data.creeps = _.sortBy(task.data.creeps,(e:string)=>{
                
                if(Game.creeps[e].ActiveRole() =='porter')
                {
                    if(Game.creeps[e].pos.distance(bindMine.BasePosition)>3)
                    {
                        return 0
                    }
                    return -Game.creeps[e].store.getUsedCapacity()-1;
                } 
                else 
                {
                    return 0;
                }
            })

        }
        return ETaskState.Running
    }
    
    private static checkHarvestDepo(room:Room,task:ITask<ICreepTaskData<"depo">>):ETaskState
    {
        // room.log("warn",`checkHarvestDepo`)
        const workroom = Game.rooms[task.data.arg.target.roomName];
        if(!workroom)
        {
            return ETaskState.Running
        }
        const depo = Game.getObjectById(task.data.arg.target.id);
        if(!depo)
        {
            return ETaskState.Complete;
        }
        if(depo.lastCooldown>100)
        {
            task.data.required=[];
            if(task.data.creeps.length==0)
            {
                return ETaskState.Complete;
            }
        }
        if(task.data.creeps.length>1)
        {
            task.data.creeps = _.sortBy(task.data.creeps,(e:string)=>{
                
                if(Game.creeps[e].ActiveRole() =='porter')
                {
                    if(Game.creeps[e].pos.distance(depo.pos)>3)
                    {
                        return 0
                    }
                    return -Game.creeps[e].store.getUsedCapacity()-1;
                } 
                else 
                {
                    return 0;
                }
            })
             
            
        }
        
        
        return ETaskState.Running
    }
    private static checkBuild(room:Room,task:ITask<ICreepTaskData<"build">>):ETaskState
    {
         
        let build = false;
        let sum_progress=0;
        if(Game.rooms[task.data.room!])
        {
            // 检测修建完成与否
            for(let i=0;i<task.data.arg.Objects.length;)
            {
                const object = Game.getObjectById(task.data.arg.Objects[i].id) as ConstructionSite;
                // 如果目标所在的房间也美哟视野了
                if(!object)
                {
                    task.data.arg.Objects.splice(i,1);
                    build = true;
                }
                else
                {
                    sum_progress+=(object.progressTotal-object.progress)
                    i++;
                }
            }
            if(build)
            {
                this.notify(room.name,{type:"BuildItemComplete",region:room.lordRoom().name,room:room.name});
            }
            if(task.data.arg.Objects.length==0)
            {
                this.notify(room.name,{type:"BuildComplete",region:room.lordRoom().name,room:room.name});
                return ETaskState.Complete
            }
        }
        if(room.canExecute(137))
        {
            // 更新建筑工数量
            const creeps =  task.data.creeps.map(e=>Game.creeps[e]);
            const workprogress = BodyEfficiency.getWorkProgress(creeps,"build");
            const spawnContainers = room.getEntity("SpawnEntity").getContainer().map(e=>Game.getObjectById(e) as StructureContainer).filter(e=>e);
            if(workprogress>sum_progress*3)
            {
                // 剩余的爬已经就可以完成了,或者能量没了
                task.data.required[0][1]= 1;
            }
            else  if ((spawnContainers.length  && spawnContainers.every(e=>e.store.getUsedCapacity() == 0)))
            {
                task.data.required[0][1]--;
                task.data.required[0][1]= Math.max( task.data.required[0][1],1);
            }
            else 
            {
                task.data.required[0][1]= Math.max( task.data.required[0][1],1);
            }
        }
        return ETaskState.Running
    }

    private static checkHelpBuild(room:Room,task:ITask<ICreepTaskData<"helpBuild">>):ETaskState
    {
        const obj = task.data.required.find(e=>e[0].includes("worker"));
        if(obj)
        {
            if(task.data.arg.Objects?.length ==0  && task.data.creeps.length ==0)
            {
                return ETaskState.Complete
            }
        }
        else 
        {
            if(Game.rooms[task.data.room].controller?.level ==8)
            {
                return  ETaskState.Complete;
            }
        }
        
        if(task.data.room && Game.rooms[task.data.room])
        {
            if(!task.data.arg.Objects)
            {
                task.data.arg.Objects = _.sortBy( Game.rooms[task.data.room].find(FIND_CONSTRUCTION_SITES),(e:ConstructionSite)=>
                {
                    return structurePriority[e.structureType]?structurePriority[e.structureType]:100
                }).map(e=> PositionHelper.getObjectRef(e) as Required<ObjectRef> )
            }
            let build = false;
            for(let i=0;i<task.data.arg.Objects.length;)
            {
                const object = Game.getObjectById(task.data.arg.Objects[i].id) as ConstructionSite;
                if(!object)
                {
                    task.data.arg.Objects.splice(i,1);
                    build = true;
                }
                else
                {
                    i++;
                }
            }
            if(build)
            {
                // 援建不用抛事件
                if(Game.rooms[task.data.room].controller?.my)
                {
                    this.notify(task.data.room,{type:"BuildItemComplete",region:task.data.room,room:task.data.room});
                }
                
            }
            if(task.data.arg.Objects.length==0)
            {
                // 建筑工业务
                const sites = _.sortBy(Game.rooms[task.data.room].getConstructSites(), (e:ConstructionSite)=>
                {
                    return structurePriority[e.structureType]?structurePriority[e.structureType]:100
                })
                const obj = task.data.required.find(e=>e[0].includes("worker"));
                if(!obj)
                {
                    return ETaskState.Running
                }
                if(sites.length)
                {
                    task.data.arg.Objects = sites.map(e=>PositionHelper.getObjectRef(e) as Required<ObjectRef>);
                    obj[1]= obj[2]!;
                    return ETaskState.Running
                }
                if(obj)
                {
                    

                    // obj[1]=0;
                    task.data.required.forEach(e=>e[1]=0)
                    Game.rooms[task.data.room].log('info',`援助建造完成!${task.data.room}`);
                     this.notify(task.data.room,{type:"BuildComplete",region:task.data.room,room:task.data.room});
                }
                
                // task.data.required=[];
            }
        }
        
        return ETaskState.Running
    }
    private static checkRepair(room:Room,task:ITask<ICreepTaskData<"repair">>):ETaskState
    {
        const core= room.getEntity("CoreEntity");
        if(core && core.Storage )
        {
            const count = core.resourceCount(RESOURCE_ENERGY);
            if(count<120000)
            {
                task.data.required.forEach(e=>e[1]=1);
            }
            if(count<10000)
            {
                return ETaskState.Complete
            }
            const level = room.controller?.level as number;
            const workroom = Game.rooms[task.data.arg.room];
            // 爬的总数。计数
            if(room.getType() ==1 &&  !room.isSafe())
            {
                if(task.data.required[0][1]<=2)
                {
                    task.data.required[0][1]=4;
                }
            }
            else 
            {
                if(workroom && room.canExecute(50+100*(level-1)))
                {
                    // 每400T检测一次爬的数量
                    let leftProgress = 0;
                    for(let k of  task.data.arg.targets)
                    {
                        let hits = Game.getObjectById(k[0])?.hits;
                        let goalhit =k[1] ;
                        leftProgress+= goalhit  - (hits?hits:0);
                    }
                    const creeps  = task.data.creeps.map(e=>Game.creeps[e]);
                    const workeffect =  BodyEfficiency.getWorkProgress(creeps,"repair")*2;
                    if(leftProgress<workeffect)
                    {
                        task.data.required.forEach(e=>e[1]=1);
                    }
                }
            }
        }
        if(task.data.arg.targets.length==0)
        {
           
            return ETaskState.Complete
        }

        return ETaskState.Running
    }

    private static checkScout(room:Room,task:ITask<ICreepTaskData<"scout">>):ETaskState
    {
        const creeps = task.data.creeps;
        if(creeps.length>0 && !Game.creeps[creeps[0]])
        {
            // 爬死了.
            return ETaskState.Complete
        }
        return ETaskState.Running
    }
    private static checkUpgrade(room:Room,task:ITask<ICreepTaskData<"upgrade">>):ETaskState
    {
        // const controller = room.getEntity("ControllerEntity");
        // const contanier = controller.getContainer();
        // if(controller && controller.getContainer().length>0)
        // {
        //     return ETaskState.Complete
        // }
        return ETaskState.Running
    }
    private static checkFill(room:Room,task:ITask<ICreepTaskData<"fill">>):ETaskState
    {
        const first = task.data.arg.targets[0];
        if(first)
        {
            const obj = (Game.getObjectById(first) as AnyStoreStructure);
            if(!obj || obj.store.getFreeCapacity(RESOURCE_ENERGY)==0 || (obj.structureType == STRUCTURE_TOWER && obj.store.getFreeCapacity(RESOURCE_ENERGY)<20))
            {
                task.data.arg.targets.splice(0,1);
            }
        }
        
        if(task.data.arg.targets.length==0)
        {
            return ETaskState.Complete
        }
        return ETaskState.Running
    }

    private static checkClaim(room:Room,task:ITask<ICreepTaskData<"claim">>):ETaskState
    {
        if(task.data.arg.action == "claim" && Game.rooms[task.data.arg.room]?.controller?.my)
        {
            return ETaskState.Complete;
        }
        if(task.data.arg.action == "reserve")
        {
            
                if(room.controller!.level>=4)
                {
                    if(room.canExecute(200))
                    {
                        const ret = task.data.required.find(e=>e[0][0] == "claimer") ;
                        const targetroom =  Game.rooms[task.data.arg.room];
                        if(ret&& targetroom)
                        {
                            if(targetroom.controller!.reservation && targetroom.controller!.reservation.ticksToEnd>4000)
                            {
                                ret[1]=0;
                                if(task.data.creeps.map(e=>Game.creeps[e]).filter(c=>c).length ==0)
                                {
                                    return ETaskState.Complete;
                                }
                            }
                            else 
                            {
                                ret[1]=1;
                            }
                            
                        }
                    }
                    
                }
                else 
                {
                    if(room.canExecute(1301))
                    {
                        const targetroom =  Game.rooms[task.data.arg.room];
                        if(targetroom&& targetroom.controller)
                        {
                            const ret = task.data.required.find(e=>e[0][0] == "claimer") 
                            if(ret)
                            {
                                ret[1]=Math.min(2,PositionHelper.getFreeSpace(targetroom.controller.pos,1).length);
                                
                            }
                        }
                    }
                    
                }
             
        }
        return ETaskState.Running
    }
    private static checkTransport(room:Room,task:ITask<ICreepTaskData<"transport">>):ETaskState
    {
        if(Game.rooms[task.data.arg.To.roomName] && !Game.getObjectById(task.data.arg.To.id as Id<Structure>))
        {
            return ETaskState.Complete
        }
        if(task.data.arg.amount === 0)
        {
            return ETaskState.Complete
        }

        return ETaskState.Running
    }
    private static checkTransportAccurate(room:Room,task:ITask<ICreepTaskData<"transportAccurate">>):ETaskState
    {
        if(task.data.arg.List.length==0)
        {
            return ETaskState.Complete
        }

        return ETaskState.Running
    }
}